`include "PicoDefines.v"

module E12toPicoBusBridge(
   input  Clk,
   input  [31:0]MemAddress,
   input  [15:0]DataIn,
   output [15:0]DataOut,
   input  MemRead,
   input  MemWrite,
   output PicoRst,
   output PicoClk,
   output [31:0]PicoAddr,
   output reg [31:0]PicoDataIn,
   input  [31:0]PicoDataOut,
   output PicoRd,
   output PicoWr
);

reg Odd;
reg DataRd_0;
reg DataRd = 0;
reg DataWr_0;
reg DataWr = 0;
reg [31:0]Read;
reg [31:0]ReadAddress;
reg [31:0]WriteAddress;
reg [7:0] RstCount=8'h0;
wire InternalRst;
//synthesis attribute init DataRd 0
//synthesis attribute init DataWr 0

reg PicoClk_ = 1'b0;
always @(posedge Clk)
   PicoClk_ <= ~PicoClk_;
BUFG PicoClk_BUFG(.I(PicoClk_), .O(PicoClk));

//Reset
always @(posedge PicoClk)
   RstCount <= RstCount + 1;
SRL16 #(.INIT(16'hFFFF)) RESET_SRL(.Q(InternalRst), .A0(1'b1), .A1(1'b0), .A2(1'b0), .A3(1'b0), .CLK(RstCount[7]), .D(1'b0));

assign PicoRst = InternalRst;

//Read
always @(posedge PicoClk) DataRd_0 <= DataRd;               //assign DataRd delay
	
always @(posedge PicoClk)
   begin
   if (MemRead & ~DataRd)                                   //If MemRead is high and not already reading...
      begin
      if (~MemAddress[1])                                   //If this is an even read...
         begin
         DataRd            <= 1;                            //Set reading signal high
         ReadAddress[31:0] <= { MemAddress[31:2], 2'h0 };   //Increment address
         Odd               <= MemAddress[1];
         end
      end
   else
   if (MemRead & DataRd & ~DataRd_0)                        //Only on valid PicoRd signal...                              
      Read[31:0]        <= PicoDataOut[31:0];               //Latch incoming data
   else      
   if (~MemRead & DataRd)                                   //If MemRead is low and reading signal is set...
      begin
      DataRd            <= 0;                               //Set reading signal low
      if (Odd)
         Read[31:0]     <= 32'h0;                           //Clear reading latch
      end
   end

assign DataOut[15:0] = MemRead ? (MemAddress[1] ? Read[31:16] : Read[15:0]) : 16'h0;
assign PicoRd = DataRd & ~DataRd_0;
//Write
always @(posedge PicoClk) DataWr_0 <= DataWr;

always @(posedge PicoClk)
   begin
   if (MemWrite & ~DataWr)                                  //If MemWrite is high and not already writing...
      begin
      if (MemAddress[1])                                    //If this is an even write...
         begin
         PicoDataIn[31:16] <= DataIn[15:0];                 //Store data in upper 16 bits of PicoDataIn and
         DataWr            <= 1;                            //set writing signal high and
         WriteAddress[31:0]<= { MemAddress[31:2], 2'h0 };   //set WriteAddress
         end
      else
      begin
         PicoDataIn[15:0]  <= DataIn[15:0];                 //If this an odd write, store data in lower 16 bits of PicoDataIn
      end
   end
   else
   if (~MemWrite & DataWr)                                  //If MemWrite is low and writing signal is set...
      begin
      DataWr               <= 0;                            //Set writing signal low
      end
   end

assign PicoWr   = DataWr & ~DataWr_0;
assign PicoAddr = MemRead ? ReadAddress[31:0] : WriteAddress[31:0];

endmodule

